#include "Odfconvert.h"
#include <iterator>
#include <fstream>
#include <Tools.h>
#include <boost/filesystem.hpp>
#include <boost/process.hpp>
#include <iostream>

//utf8
#include "utf8.h"

//xmlwrapp headers
#include <xsltwrapp/xsltwrapp.h>
#include <xmlwrapp/xmlwrapp.h>


//! EventParser 
/*!
Trieda sluziaca ako receptor udalosti ktore vznikaju pri
parsovani xml dokumentu.
*/
class EventParser : public xml::event_parser
{
public:

	std::wstring GetText()
	{
		return myParsedText;
	}

private:
	std::wstring myParsedText;

	//! text (private )
	/*!
		Metoda sa zavola ak sa nacita text z xml dokumentu
		\param const std::string & theInput nacitany text
		\return bool true
	*/
	bool text (const std::string &theInput)
	{
		utf8::utf8to16(theInput.begin(),theInput.end(),back_inserter(myParsedText));
		return true;
	}

	bool start_element (const std::string &name, const attrs_type&)
	{
		return true;
	}


	bool end_element (const std::string &name)
	{ 
		if(name == "text:p")	
		{
			myParsedText.append(L"\n");
		}
		return true;   
	}

};

Odfconvert::Odfconvert(void)
{
	myZipfile = NULL;
	std::string aXSLFileName = "odt2html.xsl";
	std::string aPluginPath;

	boost::process::self &mySelf = boost::process::self::get_instance();
	boost::process::environment env = mySelf.get_environment();
	for(boost::process::environment::iterator it = env.begin(); it != env.end(); ++it)
	{
		if (it->first == "plag_plugin_path")
		{
			aPluginPath = it->second;
		}
	}

	if(aPluginPath.empty())
	{
		std::cerr << "Cant find the enviroment variable plag_plugin_path, please set it first.." << std::endl;
		throw std::runtime_error("no enviroment variable");
	}

	myXSLFile = aPluginPath + aXSLFileName;

	if(!boost::filesystem::exists(myXSLFile))
	{
		throw std::runtime_error("Cant find :" +myXSLFile);
	}
}

Odfconvert::~Odfconvert(void)
{
	delete myZipfile;
}

bool Odfconvert::Open(PComunicator::PFileInfo &theFile)
{
	if(!theFile.GetFileType().empty() && theFile.GetFileType() != "odt")
		return false;

	delete myZipfile;
	myOdtName = theFile.GetFullName();

	try
	{
		myZipfile = new zipios::ZipFile(theFile.GetFile());
		zipios::ConstEntries entries = myZipfile->entries();
		zipios::ConstEntries::iterator iter;

		for(iter = entries.begin(); iter != entries.end(); iter++)
		{
			if( (*iter)->isDirectory())
				continue;		
			else
			{
				if( (*iter)->getFileName() == "content.xml" )
				{
					std::string fullFileName = (*iter)->getName();
					zipios::ConstEntryPointer entri = myZipfile->getEntry(fullFileName,zipios::FileCollection::ZIP_MATCH);
					std::istream *pIstream = myZipfile->getInputStream(entri);
					myOdtFile.assign(std::istreambuf_iterator<char>((*pIstream)), std::istreambuf_iterator<char>());
					delete pIstream;
					return true;
				}
			}
		}

		return true;
	}
	catch(std::exception)
	{
		return false;
	}

	return false;
}


std::wstring Odfconvert::Read()
{
	EventParser _parser;
	_parser.parse_chunk(myOdtFile.c_str(),myOdtFile.size());

	return _parser.GetText();
}


std::string Odfconvert::CreateHtml(std::string thePath)
{
	if(!boost::filesystem::exists(thePath))
	{
		boost::filesystem::create_directories(thePath);
	}

	//parsujeme hlavny document z docx suboru(content.xml)
	xml::tree_parser parser(myOdtFile.c_str(),myOdtFile.size());
	xml::document &doc = parser.get_document();

	//treba rozparsovat XSL dokument pouzity na transformaciu
	xslt::stylesheet style(myXSLFile.c_str());

	//pouzijeme xsl transformaciu
	xml::document &result = style.apply(doc);

	std::string _newName = myOdtName;
	Tools::Replace<std::string>(_newName,".odt",".html");

	std::string _newFullPath = thePath+_newName; 

	std::ofstream writer(_newFullPath.c_str());

	//vysledok transformacie zapiseme do suboru
	writer << result;
	writer.close();

	return _newFullPath;
}

std::string Odfconvert::Format()
{
	return "odt";
}

char* Odfconvert::Autor()
{
	return "Marek Szanyi";
}

char* Odfconvert::Version()
{
	return "1.0";
}